/*******************************************************************************
 * Copyright (c) 2011 EclipseDevX.org and others.
 * 
 * All rights reserved. This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License v1.0 which
 * accompanies this distribution, and is available at:
 * 
 *     http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/

package org.eclipsedevx.core.workspace;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.resources.ISavedState;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipsedevx.core.DevXCorePlugin;

/**
 * 
 * 
 * 
 * @author dcarew
 */
public class WorkspaceListener implements IResourceChangeListener, ISaveParticipant {
	
	private static WorkspaceListener workspaceListener;
	
	public static WorkspaceListener getInstance() {
		if (workspaceListener == null) {
			workspaceListener = new WorkspaceListener();
		}
		
		return workspaceListener;
	}
	
	@SuppressWarnings("deprecation")
  private WorkspaceListener() {
		ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
		
		try {
			ISavedState savedState = ResourcesPlugin.getWorkspace().addSaveParticipant(DevXCorePlugin.getPlugin(), this);
			
			notifyListenersRestore();
			
			if (savedState != null) {
				savedState.processResourceChangeEvents(this);
			}
		} catch (CoreException ce) {
			DevXCorePlugin.logError(ce);
		}
	}

	// IResourceChangeListener
	
	public void resourceChanged(IResourceChangeEvent event) {
		handleResourceDelta(event.getDelta());
	}
	
	private void handleResourceDelta(IResourceDelta delta) {
		IResource resource = delta.getResource();
		
		if (resource instanceof IProject) {
		    notifyListenersChange((IProject)resource, delta);
		} else {
			for (IResourceDelta child : delta.getAffectedChildren()) {
				handleResourceDelta(child);
			}
		}
	}

	// ISaveParticipant
	
	public void prepareToSave(ISaveContext context) throws CoreException {
		
	}

	public void saving(ISaveContext context) throws CoreException {
	    if (context.getKind() == ISaveContext.FULL_SAVE) {
	        notifyListenersSave();
	    }
	    
		context.needDelta();
	}
	
	public void doneSaving(ISaveContext context) {
		
	}

	public void rollback(ISaveContext context) {
		
	}
	
    private void notifyListenersRestore() {
        for (IWorkspaceChangeListener listener : ChangeListenersManager.getListeners()) {
            try {
                listener.restore();
            } catch (Throwable t) {
                DevXCorePlugin.logError(t);
            }
        }
    }
    
	private void notifyListenersChange(IProject project, IResourceDelta delta) {
		for (IWorkspaceChangeListener listener : ChangeListenersManager.getListeners()) {
			try {
				listener.handleChange(project, delta);
			} catch (CoreException e) {
				// ignore
				
			} catch (Throwable t) {
				DevXCorePlugin.logError(t);
			}
		}
	}

    private void notifyListenersSave() {
        for (IWorkspaceChangeListener listener : ChangeListenersManager.getListeners()) {
            try {
                listener.save();
            } catch (Throwable t) {
                DevXCorePlugin.logError(t);
            }
        }
    }
    
}
